﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;


namespace AndroidRTLPatcher
{
    // This class was created by Elad Avron using libraries by the IC#Code group, available at http://www.icsharpcode.net/opensource/sharpziplib/ //
    public class cszip
    {
        public void FastZipExtract(string pathToZip, string saveFolderPath, string filterString)
        {
            //Checks that the source file and target dir exist, and if not, throw it back at the calling program to handle
            if (!File.Exists(pathToZip))
            {
                throw new Exception("Source file not found! \n Path requested: " + pathToZip);
            }
            if(!Directory.Exists(saveFolderPath))
            {
                throw new Exception("Target directory does not exist! \n Path requested: " + saveFolderPath);
            }
            // Start the process //
            string jarPath = pathToZip;
            string savePath = saveFolderPath;
            try
            {               
                FastZip zipFile = new FastZip();
                zipFile.ExtractZip(jarPath, saveFolderPath, filterString);
            }
            catch (Exception ex)
            {
                throw ex; //Throw it back to the program
            }
        } //Extract files using FastZip - quick and dirty, gets the job done but not very versatile. Directory structure will be recreated.
        public void FastZipSave(string pathToZip, string fileToSave, string filetoSaveAs)
        {
            if (!File.Exists(pathToZip))
            {
                throw new Exception("JAR file not found! \n Path requested: " + pathToZip);
            }
            if (!File.Exists(fileToSave))
            {
                throw new Exception("File to save does not exist! \n Path requested: " + fileToSave);
            }
            try
            {
                ZipFile zipFile = new ZipFile(pathToZip);
                zipFile.BeginUpdate();
                zipFile.Add(fileToSave, filetoSaveAs);
                zipFile.CommitUpdate();
                zipFile.Close();
            }
            catch (Exception ex)
            {
                throw ex; //Throw it back to the program
            }
        } //Save a file into Zip using FastZip.
        public void manualZipExtract(string pathToZip, string saveFolderPath, string filterString, Boolean removeDirectories) //Extract files using the manual method - allows greater control over paths and outputs.
        {
            ZipFile zf = null; //empty existing objects
            try
            {
                FileStream fs = File.OpenRead(pathToZip);
                zf = new ZipFile(fs);
                foreach (ZipEntry zipEntry in zf)
                {
                    if (!zipEntry.IsFile)
                    {
                        continue;			// Ignore directories
                    }
                    String entryFileName = zipEntry.Name;
                    if (removeDirectories)
                    {
                        entryFileName = Path.GetFileName(entryFileName); // to remove the folder from the entry
                    }
                    if (filterString != null && Path.GetFileName(entryFileName) != filterString)
                    {
                        continue;
                    }
                    byte[] buffer = new byte[4096];		// 4K is optimum
                    Stream zipStream = zf.GetInputStream(zipEntry);

                    // Manipulate the output filename here as desired.
                    String fullZipToPath = Path.Combine(saveFolderPath, entryFileName);
                    string directoryName = Path.GetDirectoryName(fullZipToPath);
                    if (directoryName.Length > 0)
                        Directory.CreateDirectory(directoryName);

                    // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
                    // of the file, but does not waste memory.
                    // The "using" will close the stream even if an exception occurs.
                    using (FileStream streamWriter = File.Create(fullZipToPath))
                    {
                        StreamUtils.Copy(zipStream, streamWriter, buffer);
                    }
                }
            }
            finally
            {
                if (zf != null)
                {
                    zf.IsStreamOwner = true; // Makes close also shut the underlying stream
                    zf.Close(); // Ensure we release resources
                }
            }
        }
        public string findFile(string pathToZip, string searchString)
        {
            if (!File.Exists(pathToZip))
            {
                throw new Exception("Zip file not found! \n Path requested: " + pathToZip);
            }
            ZipInputStream streamZip = new ZipInputStream(File.OpenRead(pathToZip));
            ZipEntry objEntry;
            do
            {
                objEntry = streamZip.GetNextEntry();
                if (objEntry == null)
                {
                    return null;
                }

                if (Path.GetFileName(objEntry.Name) == searchString)
                {
                    return objEntry.Name;
                }
            } while (objEntry != null);
            //default fallback
            return null; ;
        } //Find a file in the ZIP and return it's path (null if not found)
      }
}

